using System;
using System.ComponentModel;
using System.Windows;
using Microsoft.VisualStudio.ExtensionsExplorer;
using Microsoft.VisualStudio.ExtensionsExplorer.UI;
using System.Collections.Generic;
using System.Globalization;
using VsxFactory.ExtensionManager.Properties;

namespace VsxFactory.ExtensionManager.Providers
{
    /// <summary>
    /// Base class for all tree node types.
    /// </summary>
    internal abstract class PackagesProviderBase : VsExtensionsProvider {

        private PackagesSearchNode _searchNode;
        private PackagesTreeNodeBase _lastSelectedNode;

        private object _mediumIconDataTemplate;
        private object _detailViewDataTemplate;
        private IList<IVsSortDescriptor> _sortDescriptors;

        protected PackagesProviderBase() {
        }

        public virtual bool RefreshOnNodeSelection {
            get {
                return false;
            }
        }

        public PackagesTreeNodeBase SelectedNode { 
            get; 
            set; 
        }

        public bool SuppressNextRefresh { get; private set; }

        /// <summary>
        /// Gets the root node of the tree
        /// </summary>
        protected IVsExtensionsTreeNode RootNode {
            get;
            set;
        }

        public PackageSortDescriptor CurrentSort
        {
            get;
            set;
        }

        public override IVsExtensionsTreeNode ExtensionsTree {
            get {
                if (RootNode == null) {
                    RootNode = new RootPackagesTreeNode(null, String.Empty);
                    CreateExtensionsTree();
                }

                return RootNode;
            }
        }
        

        public IList<IVsSortDescriptor> SortDescriptors
        {
            get
            {
                if (_sortDescriptors == null)
                {
                    _sortDescriptors = CreateSortDescriptors();
                }
                return _sortDescriptors;
            }
        }

        protected virtual IList<IVsSortDescriptor> CreateSortDescriptors()
        {
            return new List<IVsSortDescriptor> {
//                new PackageSortDescriptor(Resources.Dialog_SortOption_MostDownloads, "DownloadCount", ListSortDirection.Descending),
//                new PackageSortDescriptor(Resources.Dialog_SortOption_HighestRated, "Rating", ListSortDirection.Descending),
                new PackageSortDescriptor(String.Format(CultureInfo.CurrentCulture, "{0}: {1}", "Name", "Ascending"), "Name"),
                new PackageSortDescriptor(String.Format(CultureInfo.CurrentCulture, "{0}: {1}", "Name", "Descending"), "Name", ListSortDirection.Descending)
            };
        }

        public override string ToString() {
            return Name;
        }

        public override IVsExtensionsTreeNode Search(string searchText)
        {
            if (OperationCoordinator.IsBusy) {
                return null;
            }

            if (!String.IsNullOrEmpty(searchText) && SelectedNode != null)
            {
                if (_searchNode != null)
                {
                    _searchNode.SetSearchText(searchText);
                }
                else
                {
                    _searchNode = new PackagesSearchNode(this, this.RootNode, SelectedNode, searchText);
                    AddSearchNode();
                }
            }
            else
            {
                RemoveSearchNode();
            }

            return _searchNode;
        }

        private void RemoveSearchNode() {
            if (_searchNode != null)
            {

                // When remove the search node, the dialog will automatically select the first node (All node)
                // Since we are going to restore the previously selected node anyway, we don't want the first node
                // to refresh. Hence suppress it here.
                SuppressNextRefresh = true;

                try
                {
                    // dispose any search results
                    RootNode.Nodes.Remove(_searchNode);
                }
                finally
                {
                    _searchNode = null;
                    SuppressNextRefresh = false;
                }

                if (_lastSelectedNode != null)
                {
                    // after search, we want to reset the original node to page 1 (Work Item #461) 
                    _lastSelectedNode.CurrentPage = 1;
                    SelectNode(_lastSelectedNode);
                }
            }
        }

        private void AddSearchNode()
        {
            if (_searchNode != null && !RootNode.Nodes.Contains(_searchNode))
            {
                // remember the currently selected node so that when search term is cleared, we can restore it.
                _lastSelectedNode = SelectedNode;

                RootNode.Nodes.Add(_searchNode);
                SelectNode(_searchNode);
            }
        }

        protected void SelectNode(PackagesTreeNodeBase node) {
            node.IsSelected = true;
            SelectedNode = node;
        }

        private void CreateExtensionsTree() {
            // The user may have done a search before we finished getting the category list; temporarily remove it
            RemoveSearchNode();

            // give subclass a chance to populate the child nodes under Root node
            FillRootNodes();

            // Re-add the search node and select it if the user was doing a search
            AddSearchNode();
        }


        protected virtual void FillRootNodes() {
        }

        // Mapping between NuGet entity and extension manager entity
        public IVsExtension CreateExtension(IPackageRepository repository, DataServicePackage package)
        {
            return new Microsoft.VisualStudio.ExtensionManager.UI.VSGalleryEntry()
            {
                IsSelected = true,
                Name = package.Name,
                VsixID = package.Name + package.Version,
                Description = package.Description,
                DownloadUrl = String.Format("{0}/Packages(Name='{1}',Version='{2}')/$value", repository.Source, package.Name, package.Version),
                Author = String.Join(", ", package.Author),
                VsixVersion = package.Version.ToString(),
                DownloadCount = 0,
                Icon = package.Icon,
                Rating = 0,
                RatingsCount = 1,
                MoreInfoURL = package.MoreInfoUrl
            };
        }

        // Extension manager data templates
        public override object DetailViewDataTemplate
        {
            get
            {
                if (this._detailViewDataTemplate == null)
                {
                    ResourceDictionary dictionary = new ResourceDictionary();
                    dictionary.Source = new Uri("Microsoft.VisualStudio.ExtensionManager.Implementation;component/UI/OnlineProviderTemplates.xaml", UriKind.Relative);
                    this._detailViewDataTemplate = dictionary["OnlineDetailTemplate"];
                }
                return this._detailViewDataTemplate;
            }
        }

        public override object MediumIconDataTemplate
        {
            get
            {
                if (this._mediumIconDataTemplate == null)
                {
                    ResourceDictionary dictionary = new ResourceDictionary();
                    dictionary.Source = new Uri("Microsoft.VisualStudio.ExtensionManager.Implementation;component/UI/OnlineProviderTemplates.xaml", UriKind.Relative);
                    this._mediumIconDataTemplate = dictionary["OnlineTileTemplate"];
                }
                return this._mediumIconDataTemplate;
            }
        }
    }
}
